unit uLBMPPackage;

interface

uses
  SysUtils, Classes, uDZPersistent, uGxtMobileLocateNative;

type
  TRequestType = (rtUnknown, rtServerInfo, rtGetState, rtReg, rtAgreeReg, rtUnReg,
    rtCityLoc, rtCoordLoc, rtShowMap);

  TLbmpPkgHdr = packed record
  public
    function IsValid: Boolean;
    function ReqTypeName: string; inline;
  public
    Signature: array [0..3] of AnsiChar;  //'lbmp'
    HdrLen: Word;
    Format: Word;
    ReqType: Word; //TRequestType
    Option: Word;
    DataLen: Integer;
  end;
  PLbmpPkgHdr = ^TLbmpPkgHdr;

  TRequestPackage = class(TDzPersistent)
  private
    fSendTime: TDateTime;
    fSerialNo: Integer;
  protected
    fReqType: TRequestType;
  public
    constructor Create; override;
    property ReqType: TRequestType read fReqType;
  published
    property SendTime: TDateTime read fSendTime write fSendTime;
    property SerialNo: Integer read fSerialNo write fSerialNo;
  end;

  TRequestClass = class of TRequestPackage;

  TResponsePackage = class(TDzPersistent)
  private
    fSendTime: TDateTime;
    fErrCode: Integer;
    fErrMsg: WideString;
    fSerialNo: Integer;
  public
    constructor Create; override;
  published
    property SerialNo: Integer read fSerialNo write fSerialNo;
    property SendTime: TDateTime read fSendTime write fSendTime;
    property ErrCode: Integer read fErrCode write fErrCode;
    property ErrMsg: WideString read fErrMsg write fErrMsg;
  end;

  TResponseClass = class of TResponsePackage;

  TOperationResult = class(TDzPersistent)
  private
    fErrCode: Integer;
    fErrMsg: WideString;
    fState: TLbmpSvcState;
    fPhone: AnsiString;
    function IsSuccess: Boolean;
  public
    property Success: Boolean read IsSuccess;
  published
    property Phone: AnsiString read fPhone write fPhone;
    property ErrCode: Integer read fErrCode write fErrCode;
    property ErrMsg: WideString read fErrMsg write fErrMsg;
    property State: TLbmpSvcState read fState write fState; 
  end;

  TCityLocResult = class(TOperationResult)
  private
    fTelCode: Integer;
    fProvinceName: WideString;
    fCityName: WideString;
  published
    property TelCode: Integer read fTelCode write fTelCode;
    property ProvinceName: WideString read fProvinceName write fProvinceName;
    property CityName: WideString read fCityName write fCityName;
  end;
  
  TCoordLocResult = class(TOperationResult)
  private
    fLatitude: AnsiString;
    fLongitude: AnsiString;
  published
    property Longitude: AnsiString read fLongitude write fLongitude;
    property Latitude: AnsiString read fLatitude write fLatitude;
  end;

  TREQSinglePhone = class(TRequestPackage)
  private
    fPhone: AnsiString;
  published
    property Phone: AnsiString read fPhone write fPhone;
  end;

  TREQMultiPhone = class(TRequestPackage)
  private
    fPhones: TStrings;
  public
    constructor Create; override;
    destructor Destroy; override;
  published
    property Phones: TStrings read fPhones write fPhones;  
  end;

  TSimpleResponse = class(TResponsePackage)
  private
    fResults: TDzPersistentList;
    procedure SetResults(const Value: TDzPersistentList);
    function GetItems(Index: Integer): TOperationResult;
    procedure SetItems(Index: Integer; const Value: TOperationResult);
  public
    constructor Create; override;
    destructor Destroy; override;
    function Add: TOperationResult;
    property Items[Index: Integer]: TOperationResult read GetItems write SetItems;
  published
    property Results: TDzPersistentList read fResults write SetResults;
  end;
  
  TREQGetState = class(TREQMultiPhone)
  public
    constructor Create; override;
  end;

  TRESGetState = TSimpleResponse;

  TREQReg = class(TREQMultiPhone)
  public
    constructor Create; override;
  end;

  TRESReg = TSimpleResponse;

  TREQAgreeReg = class(TREQMultiPhone)
  public
    constructor Create; override;
  end;

  TRESAgreeReg = TSimpleResponse;

  TREQUnReg = class(TREQMultiPhone)
  public
    constructor Create; override;
  end;

  TRESUnReg = TSimpleResponse;

  TREQCityLoc = class(TREQMultiPhone)
  public
    constructor Create; override;
  end;

  TRESCityLoc = class(TResponsePackage)
  private
    fResults: TDzPersistentList;
    procedure SetResults(const Value: TDzPersistentList);
    function GetItems(Index: Integer): TCityLocResult;
    procedure SetItems(Index: Integer; const Value: TCityLocResult);
  public
    constructor Create; override;
    destructor Destroy; override;
    function Add: TCityLocResult;
    property Items[Index: Integer]: TCityLocResult read GetItems write SetItems;
  published
    property Results: TDzPersistentList read fResults write SetResults;
  end;

  TREQCoordLoc = class(TREQMultiPhone)
  public
    constructor Create; override;
  end;

  TRESCoordLoc = class(TResponsePackage)
  private
    fResults: TDzPersistentList;
    procedure SetResults(const Value: TDzPersistentList);
    function GetItems(Index: Integer): TCoordLocResult;
    procedure SetItems(Index: Integer; const Value: TCoordLocResult);
  public
    constructor Create; override;
    destructor Destroy; override;
    function Add: TCoordLocResult;
    property Items[Index: Integer]: TCoordLocResult read GetItems write SetItems;
  published
    property Results: TDzPersistentList read fResults write SetResults;
  end;

  TREQServerInfo = class(TRequestPackage)
  public
    constructor Create; override;
  end;

  TRESServerInfo = class(TResponsePackage)
  private
    fCityLocs: Integer;
    fLaunchTime: TDateTime;
    fCoordLocErrors: Integer;
    fCityLocErrors: Integer;
    fCoordLocs: Integer;
  published
    property LaunchTime: TDateTime read fLaunchTime write fLaunchTime;
    property CityLocs: Integer read fCityLocs write fCityLocs;
    property CoordLocs: Integer read fCoordLocs write fCoordLocs;
    property CityLocErrors: Integer read fCityLocErrors write fCityLocErrors;
    property CoordLocErrors: Integer read fCoordLocErrors write fCoordLocErrors;
  end;

const
  RequestClasses: array [TRequestType] of TRequestClass =
    (nil, TREQServerInfo, TREQGetState, TREQReg, TREQAgreeReg, TREQUnReg,
    TREQCityLoc, TREQCoordLoc, nil);

  ResponseClasses: array [TRequestType] of TResponseClass =
    (nil, TRESServerInfo, TRESGetState, TRESReg, TRESAgreeReg, TRESUnReg,
    TRESCityLoc, TRESCoordLoc, nil);

  ReqTypeNames: array [TRequestType] of string =
    ('Unknown', 'ServerInfo', 'GetState', 'Register', 'AgreeReg', 'UnReg',
      'CityLoc', 'CoordLoc', 'ShowMap');

implementation

{ TOperationResult }

function TOperationResult.IsSuccess: Boolean;
begin
  Result := fErrCode = 0;
end;

{ TREQMultiPhone }

constructor TREQMultiPhone.Create;
begin
  inherited;
  fPhones := TStringList.Create;
end;

destructor TREQMultiPhone.Destroy;
begin
  fPhones.Free;
  inherited;
end;

{ TREQGetState }

constructor TREQGetState.Create;
begin
  inherited;
  fReqType := rtGetState;
end;

{ TREQReg }

constructor TREQReg.Create;
begin
  inherited;
  fReqType := rtReg;
end;

{ TREQCoordLoc }

constructor TREQCoordLoc.Create;
begin
  inherited;
  fReqType := rtCoordLoc;
end;

{ TREQCityLoc }

constructor TREQCityLoc.Create;
begin
  inherited;
  fReqType := rtCityLoc;
end;

{ TREQUnReg }

constructor TREQUnReg.Create;
begin
  inherited;
  fReqType := rtUnReg;
end;

{ TREQAgreeReg }

constructor TREQAgreeReg.Create;
begin
  inherited;
  fReqType := rtAgreeReg;
end;

{ TSimpleResponse }

function TSimpleResponse.Add: TOperationResult;
begin
  Result := TOperationResult(fResults.Add);
end;

constructor TSimpleResponse.Create;
begin
  inherited;
  fResults := TDzPersistentList.Create(TOperationResult);
end;

destructor TSimpleResponse.Destroy;
begin
  fResults.Free;
  inherited;
end;

function TSimpleResponse.GetItems(Index: Integer): TOperationResult;
begin
  Result := TOperationResult(fResults[Index]);
end;

procedure TSimpleResponse.SetItems(Index: Integer; const Value: TOperationResult);
begin
  fResults[Index].Assign(Value);
end;

procedure TSimpleResponse.SetResults(const Value: TDzPersistentList);
begin
  fResults.Assign(Value);
end;

{ TResponsePackage }

constructor TResponsePackage.Create;
begin
  fSendTime := Now;
end;

{ TRequestPackage }

constructor TRequestPackage.Create;
begin
  inherited;
  fSendTime := Now;
end;

{ TRESCityLoc }

function TRESCityLoc.Add: TCityLocResult;
begin
  Result := TCityLocResult(fResults.Add);
end;

constructor TRESCityLoc.Create;
begin
  inherited;
  fResults := TDzPersistentList.Create(TCityLocResult);
end;

destructor TRESCityLoc.Destroy;
begin
  fResults.Free;
  inherited;
end;

function TRESCityLoc.GetItems(Index: Integer): TCityLocResult;
begin
  Result := TCityLocResult(fResults[Index]);
end;

procedure TRESCityLoc.SetItems(Index: Integer; const Value: TCityLocResult);
begin
  fResults[Index].Assign(Value);
end;

procedure TRESCityLoc.SetResults(const Value: TDzPersistentList);
begin
  fResults.Assign(Value);
end;

{ TRESCoordLoc }

function TRESCoordLoc.Add: TCoordLocResult;
begin
  Result := TCoordLocResult(fResults.Add);
end;

constructor TRESCoordLoc.Create;
begin
  inherited;
  fResults := TDzPersistentList.Create(TCoordLocResult);
end;

destructor TRESCoordLoc.Destroy;
begin
  fResults.Free;
  inherited;
end;

function TRESCoordLoc.GetItems(Index: Integer): TCoordLocResult;
begin
  Result := TCoordLocResult(fResults[Index]);
end;

procedure TRESCoordLoc.SetItems(Index: Integer; const Value: TCoordLocResult);
begin
  fResults[Index].Assign(Value);
end;

procedure TRESCoordLoc.SetResults(const Value: TDzPersistentList);
begin
  fResults.Assign(Value);
end;

{ TREQServerInfo }

constructor TREQServerInfo.Create;
begin
  inherited;
  fReqType := rtServerInfo;
end;

{ TLbmpPkgHdr }

function TLbmpPkgHdr.IsValid: Boolean;
begin
  Result := (Signature[0] = 'l') and (Signature[1] = 'b') and
    (Signature[2] = 'm') and (Signature[0] = 'p') and
    (HdrLen <= 10240) and
    (Format <= Word(Ord(High(TDzArchiveFormat)))) or
    (ReqType <= Word(Ord(High(TRequestType))));
end;

function TLbmpPkgHdr.ReqTypeName: string;
begin
  Result := ReqTypeNames[TRequestType(ReqType)];
end;

end.
